package edu.hawaii.teams.halealohacli.command;

import java.util.ArrayList;
import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.resource.source.jaxb.Source;

/**
 * Sorts the Hale Aloha towers based on energy consumption.
 * 
 * @author Branden Ogata
 * 
 */
public class RankTowers implements Command {

  /**
   * Returns the list of towers and their energy consumption over a given time period. As of this
   * writing, the towers are Ilima, Lehua, Lokelani, and Mokihana.
   * 
   * @param client A WattDepotClient to find the source in.
   * @param details String instances identifying the source and date to examine.
   * @return data A String containing the energy that the source has consumed since given date. If
   * multiple data exist, places each on a new line.
   * @throws Exception Handles any problems that may occur.
   * 
   */
  @Override
  public String getData(WattDepotClient client, String... details) throws Exception {
    // Constant double used to convert from watt to kilowatt.
    final double KILO = 1000.0;
    List<String> data = new ArrayList<String>();
    String currentSource = null;
    String givenStartDate = null;
    String givenEndDate = null;

    for (String text : details) {
      // If startDate is null, then this String is the start date
      if (givenStartDate == null) {
        givenStartDate = text;
      }
      // Else if endDate is null, then this String is the end date
      else if (givenEndDate == null) {
        givenEndDate = text;
        try {
          // Parse givenStartDate and givenEndDate
          int startYear = Utility.getDate(givenStartDate, "year");
          int startMonth = Utility.getDate(givenStartDate, "month");
          int startDay = Utility.getDate(givenStartDate, "day");
          int endYear = Utility.getDate(givenEndDate, "year");
          int endMonth = Utility.getDate(givenEndDate, "month");
          int endDay = Utility.getDate(givenEndDate, "day");

          // Create XMLGregorianCalendar instances to represent beginning and end of givenDate
          XMLGregorianCalendar startDate =
              client.getLatestSensorData(client.getSources().get(0).getName()).getTimestamp();
          XMLGregorianCalendar endDate =
              client.getLatestSensorData(client.getSources().get(0).getName()).getTimestamp();

          startDate.setYear(startYear);
          startDate.setMonth(startMonth);
          startDate.setDay(startDay);
          startDate.setHour(0);
          startDate.setMinute(0);
          startDate.setSecond(0);
          startDate.setMillisecond(0);

          endDate.setYear(endYear);
          endDate.setMonth(endMonth);
          endDate.setDay(endDay);
          endDate.setHour(0);
          endDate.setMinute(0);
          endDate.setSecond(0);
          endDate.setMillisecond(0);

          // For each source in the server
          for (Source source : client.getSources()) {
            currentSource = source.getName();

            // If the source is a tower, then get energy consumed through client
            // This assumes that towers have no hyphens in their name
            if (currentSource.indexOf('-') == -1) {
              data.add(String.format("%-32s%.0f%n", currentSource,
                  client.getEnergyConsumed(currentSource, startDate, endDate, 0) / KILO));
            }
          }
        }
        catch (NumberFormatException e) {
          data.add("Error: An error occurred while parsing the date.\n\n");
        }
        catch (StringIndexOutOfBoundsException e) {
          data.add("Error: An error occurred while parsing the date; "
              + "the formatting is incorrect.\n\n");
        }
        catch (IllegalArgumentException e) {
          data.add("Error: An error occurred in using the XMLGregorianCalendar class.\n\n");
        }
        catch (BadXmlException e) {
          data.add("Error: An error occurred in the XML from the server.\n\n");
        }
        catch (MiscClientException e) {
          data.add("Error: An error occurred while retrieving data.\n\n");
        }
        catch (ResourceNotFoundException e) {
          data.add("Error: The source " + currentSource + " could not be found.\n\n");
        }
      }
    }

    // Sorts the towers based on energy consumption
    data = Utility.sortByEnergy(data);

    StringBuilder output = new StringBuilder();

    // Adds all lines to the output
    for (int i = 0; i < data.size(); i++) {
      output.append(data.get(i));
    }
    return output.toString();
  }
}